package br.ufc.great;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.Map;
import java.util.Set;

import android.app.AlertDialog;
import android.app.Dialog;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.graphics.drawable.Drawable;
import android.location.Criteria;
import android.location.Location;
import android.location.LocationManager;
import android.os.Handler;
import android.os.Message;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.ListView;
import android.widget.TextView;

import com.google.android.maps.*;

public class LocationOverlay extends ItemizedOverlay<OverlayItem> implements
		OnClickListener, OnItemClickListener {

	/*BEGIN Variáveis Controle do Mapa*/
	private ArrayList<OverlayItem> items;
	private GeoPoint currentPoint; //GeoPoint clicado
	GeoPoint aproxGeoPoint; //GeoPoint aproximado do clicado
	/*END Variáveis Controle do Mapa*/
	
	/*BEGIN Variáveis de Evento*/
	Button bt_gravar, bt_cancelar, bt_edit_cancel, bt_edit;
	ImageButton bt_excluir_nota, bt_editar_nota, bt_share_facebook, bt_find_aprox_locales;
	Dialog dialogSaveNote, dialogEditNote, menuNota;
	TextView tv_title_nota, tv_desc_nota, tv_date_nota;
	EditText et_title_edit, et_desc_edit, et_date_edit;
	Dialog dialogListLocales;
	ListView listViewLocales;
	/*Duplo click aumentar zoom*/
    private long lastTouchTime = -1;
    private static final long TIME_DOUBLE_TAP = 1000;
    private static final long TIME_INITIAL = -1;
	/*END Variáveis de Evento*/

	
	
	/*Variável Referência*/
	private MActivity mainActivity;

	
	public LocationOverlay(Drawable defaultMarker, MActivity main) {
		super(boundCenterBottom(defaultMarker));
		mainActivity = main;
		items = new ArrayList<OverlayItem>();
		populate();

	}

	public void setPutMarksEnabled(boolean isPutMarksEnabled) {
	}

	public void addNewItem(GeoPoint location, String markerText, String snippet) {
		items.add(new OverlayItem(location, markerText, snippet));
		populate();
	}

	@Override
	protected OverlayItem createItem(int i) {
		return items.get(i);
	}

	@Override
	public int size() {
		return items.size();
	}


    public boolean onTap(GeoPoint point, MapView mapView) {
		currentPoint = point;
		
		long thisTime = System.currentTimeMillis();
		if (thisTime - lastTouchTime <= TIME_DOUBLE_TAP) {
			mainActivity.myMap.getController().zoomIn();
            lastTouchTime = TIME_INITIAL;
        } else {
        	lastTouchTime = thisTime;
        }
		
		//String stringProvider = mainActivity.locationManager.getBestProvider(new Criteria(), true);
		//Location location = new Location(stringProvider);
		Location aproxLocation;
		/* Ver se o ponto escolhido ja existe no banco e mostrar a mensagem */
		//int mode = mainActivity.MODE_PRIVATE;
		//SharedPreferences prefLogin = mainActivity.getSharedPreferences(
		//		mainActivity.DbName, mode);

		

		/* Caso precise atualizar a centralização do mapa a cada toque na tela.
		float latitude = (float) (point.getLatitudeE6() / 1E6);
		float longitude = (float) (point.getLongitudeE6() / 1E6);
		location.setLatitude(latitude);
		location.setLongitude(longitude);
		mainActivity.updateLocation(location);
		*/

		//Map<String, ?> keys = prefLogin.getAll();
		
		if (mainActivity.markMap.isChecked()) {
			
			addNewItem(point, null, null);

			dialogSaveNote = new Dialog(mainActivity);

			dialogSaveNote.setContentView(R.layout.addnote);
			dialogSaveNote.setTitle("Descrição");

			dialogSaveNote.show();

			bt_gravar = (Button) dialogSaveNote.findViewById(R.id.bt_gravar);
			bt_cancelar = (Button) dialogSaveNote
					.findViewById(R.id.bt_cancelar);

			bt_gravar.setOnClickListener(this);
			bt_cancelar.setOnClickListener(this);

		} else// Se não estiver marcado para fazer ponto, busca o ponto mais
				// proximo e devolve o ponto para exibição ou edição.
		{
			aproxLocation = getAproximateGeoPoint(point);
			if (aproxLocation == null)// Não há nenhum ponto proximo ao clicado.
			{

			} else // Se tiver um ponto proximo, exibir dialogo com as
					// informações da nota cadastrada e o botão editar e excluir
					// a nota.
			{
				// Location to GeoPoint

				int latitudeAproxLocation = (int) (aproxLocation.getLatitude() * 1E6);
				int longitudeAproxLocation = (int) (aproxLocation
						.getLongitude() * 1E6);

				aproxGeoPoint = new GeoPoint(latitudeAproxLocation,
						longitudeAproxLocation);

				String[] infAboutPoint = lerBanco(aproxGeoPoint);

				menuNota = new Dialog(mainActivity);

				menuNota.setTitle("Menu nota");
				menuNota.setContentView(R.layout.nota);
				menuNota.show();

				tv_title_nota = (TextView) menuNota
						.findViewById(R.id.tv_title_nota);
				tv_desc_nota = (TextView) menuNota
						.findViewById(R.id.tv_desc_nota);
				tv_date_nota = (TextView) menuNota
						.findViewById(R.id.tv_date_nota);

				tv_title_nota.setText("Título: " + infAboutPoint[0]);
				tv_desc_nota.setText("Descrição: " + infAboutPoint[1]);
				String date = infAboutPoint[2];

				tv_date_nota.setText("Criação em: " + date.substring(0, 10)
						+ " às " + date.substring(11));

				bt_excluir_nota = (ImageButton) menuNota
						.findViewById(R.id.bt_excluir_nota);
				bt_editar_nota = (ImageButton) menuNota
						.findViewById(R.id.bt_editar_nota);
				bt_share_facebook = (ImageButton) menuNota
						.findViewById(R.id.bt_share_facebook);
				bt_find_aprox_locales = (ImageButton) menuNota.findViewById(R.id.bt_find_prox_locales);

				bt_excluir_nota.setOnClickListener(this);
				bt_editar_nota.setOnClickListener(this);
				bt_share_facebook.setOnClickListener(this);
				bt_find_aprox_locales.setOnClickListener(this);

			}
		}
		return true;
	}

	@Override
	public void onClick(View v) {

		if (v == bt_gravar) {
			EditText titulo = (EditText) dialogSaveNote
					.findViewById(R.id.et_titulo);
			EditText descricao = (EditText) dialogSaveNote
					.findViewById(R.id.et_descricao);
			/* Salvar Banco */
			salvarBanco(currentPoint, titulo.getText().toString(), descricao
					.getText().toString());

			// mainActivity.addProximityAlert(currentPoint.getLatitudeE6() /
			// 1E6, currentPoint.getLongitudeE6() / 1E6);

			/*
			 * String[] array = lerBanco(currentPoint);
			 * 
			 * String t = array[0]; String d = array[1]; String time = array[2];
			 */
			dialogSaveNote.dismiss();

			mainActivity.povoarMapa();

		} else if (v == bt_cancelar) {
			dialogSaveNote.dismiss();
			OverlayItem overlayItem = new OverlayItem(currentPoint, null, null);
			items.remove(overlayItem);//Remove o item do array que representa os items do mapa
			mainActivity.myMap.getOverlays().clear(); //Limpa o mapa
			mainActivity.povoarMapa(); //Povoa novamente de acordo com o banco
		} else if (v == bt_editar_nota) {
			editNoteOnClick();

		} else if (v == bt_excluir_nota) {
			deleteNoteOnClick(aproxGeoPoint, false);
			menuNota.dismiss();

		} else if (v == bt_edit) {
			editNoteFinal();

		} else if (v == bt_share_facebook) {
			shareFacebookOnClick();

		} else if (v == bt_edit_cancel) {
			dialogEditNote.dismiss();
		}else if(v == bt_find_aprox_locales)
		{
			JsonThread jsonThread = new JsonThread(handlerHttp, "bob", aproxGeoPoint.getLatitudeE6(), aproxGeoPoint.getLongitudeE6());
			jsonThread.start();
		}

	}

	public void salvarBanco(GeoPoint g, String titulo, String descricao) {
		int mode = mainActivity.MODE_PRIVATE; // Quem pode acessar?
		SharedPreferences prefLogin = mainActivity.getSharedPreferences(
				mainActivity.DbName, mode);
		SharedPreferences.Editor editor = prefLogin.edit();

		/*
		 * Set<String> information = new HashSet<String>();
		 * 
		 * 
		 * information.add(titulo); information.add(descricao);
		 * information.add(new
		 * SimpleDateFormat("dd-MM-yyyy-hh.mm.ss").format(new Date()));
		 */
		// editor.putStringSet(information); Só aceita HashSet depois da API 11

		int latitude = g.getLatitudeE6();
		int longitude = g.getLongitudeE6();

		String latAndLng = latitude + "," + longitude;

		editor.putString(latAndLng + "t", titulo);
		editor.putString(latAndLng + "d", descricao);
		editor.putString(latAndLng + "h", new SimpleDateFormat(
				"dd-MM-yyyy-hh.mm.ss").format(new Date()));

		editor.commit();
	}

	private String[] lerBanco(GeoPoint g) {

		int mode = mainActivity.MODE_PRIVATE; // Quem pode acessar?
		SharedPreferences prefLogin = mainActivity.getSharedPreferences(
				mainActivity.DbName, mode);

		String[] array = new String[3];

		array[0] = prefLogin.getString(g.toString() + "t", "");
		array[1] = prefLogin.getString(g.toString() + "d", "");
		array[2] = prefLogin.getString(g.toString() + "h", "");

		return array;
	}

	public Location getAproximateGeoPoint(GeoPoint actPoint) // Pega o ponto
																// mais proximo
																// numa
																// distancia
																// maxima de 400
																// metros.
	{
		Location actLocation = new Location("gps");

		actLocation.setLatitude(actPoint.getLatitudeE6() / 1E6);
		actLocation.setLongitude(actPoint.getLongitudeE6() / 1E6);

		int mode = mainActivity.MODE_PRIVATE; // Quem pode acessar?
		SharedPreferences prefLogin = mainActivity.getSharedPreferences(
				mainActivity.DbName, mode);

		ArrayList<String> listPoints = new ArrayList<String>();

		Set keys = prefLogin.getAll().keySet();

		Location locationBd = new Location("gps");
		Location aproximateLocation = new Location("gps");

		for (Object object : keys) {
			String item = (String) object;
			item = item.substring(0, item.length() - 1);// Remover o ultimo
														// elemento pois é o
														// identificado de
														// titulo, desc ou data.
			String[] latAndLng = item.split(",");

			GeoPoint pointBd = new GeoPoint(Integer.parseInt(latAndLng[0]),
					Integer.parseInt(latAndLng[1]));

			locationBd.setLatitude(pointBd.getLatitudeE6() / 1E6);
			locationBd.setLongitude(pointBd.getLongitudeE6() / 1E6);

			if (actLocation.distanceTo(locationBd) < actLocation
					.distanceTo(aproximateLocation)
					&& actLocation.distanceTo(locationBd) <= 400) {
				aproximateLocation.setLatitude(locationBd.getLatitude());
				aproximateLocation.setLongitude(locationBd.getLongitude());
			}
		}

		if (aproximateLocation.getLatitude() == 0) {
			System.out.println("Retornou null no getaproximate location");
			return null;
		}
		System.out.println("apx" + aproximateLocation.getLatitude() + " "
				+ aproximateLocation.getLongitude());
		return aproximateLocation;
	}

	public Location getAproximateGeoPointToShowNotification(GeoPoint actPoint)
	{
		 // Pega o ponto mais proximo numa distancia maxima de 2000 metros.
		
		Location actLocation = new Location("gps");

		actLocation.setLatitude(actPoint.getLatitudeE6() / 1E6);
		actLocation.setLongitude(actPoint.getLongitudeE6() / 1E6);

		int mode = mainActivity.MODE_PRIVATE; // Quem pode acessar?
		SharedPreferences prefLogin = mainActivity.getSharedPreferences(
				mainActivity.DbName, mode);

		ArrayList<String> listPoints = new ArrayList<String>();

		Set keys = prefLogin.getAll().keySet();

		Location locationBd = new Location("gps");
		Location aproximateLocation = new Location("gps");

		System.out.println("apxlocation: " + aproximateLocation + "Lat: "
				+ aproximateLocation.getLatitude() + " lng: "
				+ aproximateLocation.getLongitude());

		for (Object object : keys) {
			String item = (String) object;
			item = item.substring(0, item.length() - 1);// Remover o ultimo
														// elemento pois é o
														// identificado de
														// titulo, desc ou data.
			String[] latAndLng = item.split(",");

			GeoPoint pointBd = new GeoPoint(Integer.parseInt(latAndLng[0]),
					Integer.parseInt(latAndLng[1]));

			locationBd.setLatitude(pointBd.getLatitudeE6() / 1E6);
			locationBd.setLongitude(pointBd.getLongitudeE6() / 1E6);

			// System.out.println("LatBD: "+ locationBd.getLatitude() +
			// " Lng BD: " + locationBd.getLongitude() );
			// System.out.println("LatNow: " + actLocation.getLatitude() +
			// " Lng Now: " + actLocation.getLongitude() );

			// System.out.println("Distance act to bd: " +
			// actLocation.distanceTo(locationBd));
			// System.out.println("Distance act to aproxi: " +
			// actLocation.distanceTo(aproximateLocation));

			if (actLocation.distanceTo(locationBd) < actLocation
					.distanceTo(aproximateLocation)
					&& actLocation.distanceTo(locationBd) <= 2000) {
				aproximateLocation.setLatitude(locationBd.getLatitude());
				aproximateLocation.setLongitude(locationBd.getLongitude());
			}
		}

		if (aproximateLocation.getLatitude() == 0) {
			System.out.println("Retornou null no getaproximate location");
			return null;
		}
		System.out.println("apx" + aproximateLocation.getLatitude() + " "
				+ aproximateLocation.getLongitude());
		return aproximateLocation;
	}

	public void deleteNote(GeoPoint pointToDelete) {
		int mode = mainActivity.MODE_PRIVATE; // Quem pode acessar?
		SharedPreferences prefLogin = mainActivity.getSharedPreferences(
				mainActivity.DbName, mode);
		Editor editor = prefLogin.edit();

		editor.remove(pointToDelete.toString() + "t");
		editor.remove(pointToDelete.toString() + "d");
		editor.remove(pointToDelete.toString() + "h");

		editor.commit();
	}

	public void deleteNoteOnClick(GeoPoint pointToDelete,
			boolean callOfOtherClass) {
		deleteNote(pointToDelete);
		for (int i = 0; i < items.size(); i++) {
			GeoPoint point = items.get(i).getPoint();
			if (callOfOtherClass) {
				items.remove(items.get(i));
				mainActivity.myMap.getOverlays().clear();
				mainActivity.povoarMapa();
				break;
			}
			if (point.getLatitudeE6() == aproxGeoPoint.getLatitudeE6()
					&& point.getLongitudeE6() == aproxGeoPoint.getLongitudeE6()) {
				System.out.println("apagou!");
				items.remove(items.get(i));
				mainActivity.myMap.getOverlays().clear();
				mainActivity.povoarMapa();
			}

		}
		mainActivity.povoarMapa();// Após excluir a nota, atualizar os novos
									// pontos.
		Dialog dialogShowSucess = new Dialog(mainActivity);
		dialogShowSucess.setTitle("Excluido com Sucesso");
		dialogShowSucess.show();
	}

	public void editNoteFinal()
	{
		// Esse é o editar de verdade, após o usuário ver a tela com as informações da nota e preenchida com os dados do banco, ela pode
		// editar e clicar no editar, que é a última interação da app com o usuário antes de modificar no banco.
		
		String title = et_title_edit.getText().toString();
		String desc = et_desc_edit.getText().toString();

		salvarBanco(aproxGeoPoint, title, desc);

		Dialog dialogShowSucess = new Dialog(mainActivity);
		dialogShowSucess.setTitle("Salvo com Sucesso");
		dialogShowSucess.show();
		dialogEditNote.dismiss();
		menuNota.dismiss();
	}

	public void shareFacebookOnClick() {
		String[] informationAboutPoint = lerBanco(aproxGeoPoint);
		Intent intentFacebook = new Intent(mainActivity, PostFacebook.class);

		String msgToSendToIntent = "Olá amigos, estou utilizando a aplicação para Android GeoNotes e "
				+ "ela me permite compartilhar informações Geolocalizadas com meus contatos do Facebook!"
				+ "Segue abaixo a nota: \n\n"
				+ "Título: \n"
				+ informationAboutPoint[0]
				+ "\n\n"
				+ "Descrição: \n"
				+ informationAboutPoint[1]
				+ "\n\n"
				+ "Criada em: \n"
				+ informationAboutPoint[2].substring(0, 10)
				+ " às "
				+ informationAboutPoint[2].substring(11);

		intentFacebook.putExtra("msgToPost", msgToSendToIntent);
		mainActivity.startActivity(intentFacebook);
	}

	public void shareFacebookOnClick(int position) {
		String[] informationAboutPoint = lerBanco(items.get(position)
				.getPoint());
		Intent intentFacebook = new Intent(mainActivity, PostFacebook.class);

		String msgToSendToIntent = "Olá amigos, estou utilizando a aplicação para Android GeoNotes e "
				+ "ela me permite compartilhar informações Geolocalizadas com meus contatos do Facebook!"
				+ "Segue abaixo a nota: \n\n"
				+ "Título: \n"
				+ informationAboutPoint[0]
				+ "\n\n"
				+ "Descrição: \n"
				+ informationAboutPoint[1]
				+ "\n\n"
				+ "Criada em: \n"
				+ informationAboutPoint[2].substring(0, 10)
				+ " às "
				+ informationAboutPoint[2].substring(11);

		intentFacebook.putExtra("msgToPost", msgToSendToIntent);
		mainActivity.startActivity(intentFacebook);
	}

	public void editNoteOnClick()// Edit onde o usuário vê as informações da
									// nota, e nele há o botão editar que é o
									// que realmente modifica o banco.
	{
		dialogEditNote = new Dialog(mainActivity);

		dialogEditNote.setContentView(R.layout.editnote);
		dialogEditNote.setTitle("Descrição");

		dialogEditNote.show();

		et_title_edit = (EditText) dialogEditNote
				.findViewById(R.id.et_edit_titulo);
		et_desc_edit = (EditText) dialogEditNote
				.findViewById(R.id.et_edit_descricao);

		bt_edit = (Button) dialogEditNote.findViewById(R.id.bt_edit);
		bt_edit_cancel = (Button) dialogEditNote
				.findViewById(R.id.bt_edit_cancelar);

		String[] infAboutPoint = lerBanco(aproxGeoPoint);

		et_title_edit.setText(infAboutPoint[0]);
		et_desc_edit.setText(infAboutPoint[1]);

		bt_edit.setOnClickListener(this);
		bt_edit_cancel.setOnClickListener(this);
	}
	
	String[] locales;

    final Handler handlerHttp = new Handler() {
		public void handleMessage(Message msg) {
			String[] names = msg.getData().getStringArray("names");
			locales = msg.getData().getStringArray("locales");

			if (names != null && locales != null) {
				
				dialogListLocales = new Dialog(mainActivity);
				dialogListLocales.setContentView(R.layout.listlocales);

				dialogListLocales.setTitle("Lista de Notas");
				dialogListLocales.show();

				listViewLocales = (ListView) dialogListLocales
						.findViewById(R.id.lista_locales);
				listViewLocales.setAdapter(new ArrayAdapter(mainActivity, android.R.layout.simple_list_item_1, names));

				listViewLocales.setOnItemClickListener(mainActivity.myOverlay);
				
				/*
				AlertDialog.Builder dialog = new AlertDialog.Builder(
						mainActivity);
				dialog.setTitle("Locais");
				String namesAll = "";
				for(int i=0; i<names.length; i++)
				{
					namesAll += "[" + (i+1) + "] " + names[i] + "\n";
				}
				
				dialog.setMessage(namesAll);
				dialog.create();
				dialog.show();
				*/
			}
		}
	};


	@Override
	public void onItemClick(AdapterView<?> arg0, View view, int position, long arg3) {

		String[] latAndLng = locales[position].split(",");
		int latIE6 = (int) (Float.parseFloat(latAndLng[0])*1E6);
		int lngIE6 = (int) (Float.parseFloat(latAndLng[1])*1E6);
		
		System.out.println("latie6" + latIE6 + "/" + lngIE6);
		
		GeoPoint point = new GeoPoint(latIE6, lngIE6);
		
		LocationOverlay myOtherOverlay = new LocationOverlay(mainActivity.getResources().getDrawable(R.drawable.blue_point_marker), mainActivity);
		mainActivity.myMap.getOverlays().add(myOtherOverlay);
		
		myOtherOverlay.addNewItem(point, null, null);
		
		myOtherOverlay.populate();
		
		menuNota.dismiss();
		dialogListLocales.dismiss();
		
	}
	
}
